#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include "fbtft.h"

#define DRVNAME		"fb_st7735s"
#define H_OFFSET	24
#define V_OFFSET	0

static unsigned int x_offset = 0, y_offset = 0;

static int init_display(struct fbtft_par *par)
{
	par->fbtftops.reset(par);

	/* startup sequence */
	write_reg(par, 0x01); /* software reset */

	gpiod_set_value(par->gpio.reset, 0);
	mdelay(1);
	gpiod_set_value(par->gpio.reset, 1);
	mdelay(5);

	write_reg(par, 0x11); /* sleep out */
	write_reg(par, 0x20);

	write_reg(par, 0xB1, 0x05, 0x3A, 0x3A);
	write_reg(par, 0xB2, 0x05, 0x3A, 0x3A);
	write_reg(par, 0xB3, 0x05, 0x3A, 0x3A, 0x05, 0x3A, 0x3A);
	write_reg(par, 0xB4, 0x03);

	write_reg(par, 0xC0, 0x62, 0x02, 0x04);
	write_reg(par, 0xC1, 0xC0);
	write_reg(par, 0xC2, 0x0D, 0x00);
	write_reg(par, 0xC3, 0x8D, 0x6A);
	write_reg(par, 0xC4, 0x8D, 0xEE);
	write_reg(par, 0xC5, 0x0E);

	write_reg(par, 0xE0, 0x10, 0x0E, 0x02, 0x03, 0x0E, 0x07, 0x02, 0x07, 0x0A, 0x12, 0x27, 0x37, 0x00, 0x0D, 0x0E, 0x10); 
	write_reg(par, 0xE1, 0x10, 0x0E, 0x03, 0x03, 0x0F, 0x06, 0x02, 0x08, 0x0A, 0x13, 0x26, 0x36, 0x00, 0x0D, 0x0E, 0x10);

	write_reg(par, 0x3A, 0x05);
	write_reg(par, 0x36, 0xA8);

	write_reg(par, 0x29); /* display on */

	return 0;
}

static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
{
	/* Column address */
	xs += x_offset;
	xe += x_offset;
	write_reg(par, 0x2A, (xs >> 8) & 0xff, xs & 0xff, (xe >> 8) & 0xff, xe & 0xff);

	/* Row adress */
	ys += y_offset;
	ye += y_offset;
	write_reg(par, 0x2B, (ys >> 8) & 0xff, ys & 0xff, (ye >> 8) & 0xff, ye & 0xff);

	/* Memory write */
	write_reg(par, 0x2C);
}

static int set_var(struct fbtft_par *par)
{
	switch (par->info->var.rotate) {
		case 0:
			x_offset = H_OFFSET;
			y_offset = V_OFFSET;
			write_reg(par, 0x36, 0xC0 | (!par->bgr << 3));
			break;
		case 90:
			x_offset = V_OFFSET;
			y_offset = H_OFFSET;
			write_reg(par, 0x36, 0xA0 | (!par->bgr << 3));
			break;
		case 180:
			x_offset = H_OFFSET;
			y_offset = V_OFFSET;
			write_reg(par, 0x36, 0x00 | (!par->bgr << 3));
			break;
		case 270:
			x_offset = V_OFFSET;
			y_offset = H_OFFSET;
			write_reg(par, 0x36, 0x60 | (!par->bgr << 3));
			break;
		default:
			break;
	}

	return 0;
}

static struct fbtft_display display = {
	.fbtftops = {
		.init_display = init_display,
		.set_addr_win = set_addr_win,
		.set_var = set_var,
	},
};

FBTFT_REGISTER_DRIVER(DRVNAME, "sitronix,st7735s", &display);

MODULE_ALIAS("spi:" DRVNAME);
MODULE_ALIAS("platform:" DRVNAME);
MODULE_ALIAS("spi:st7735s");
MODULE_ALIAS("platform:st7735s");

MODULE_DESCRIPTION("FB driver for the ST7735S LCD Controller");
MODULE_AUTHOR("Yuyaowen");
MODULE_LICENSE("GPL");

/************************************************************
 设备树示例，基于全志V3s主控，Linux5.10.62内核，
 可以修改的有spi总线、reset-gpios、dc-gpios、rotate.

&spi0 {
        status = "okay";
        #address-cells = <1>;
        #size-cells = <0>;

        display@0 {
                compatible = "fb_st7735s";
                reg = <0>;
                spi-max-frequency = <70000000>;

                reset-gpios = <&pio 1 4 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&pio 1 5 GPIO_ACTIVE_HIGH>;

                rotate = <0>;
                fps = <60>;
                buswidth = <8>;
                regwidth = <8>;
                width = <80>;
                height = <160>;
                bpp = <16>;
        };
};

请将此驱动程序放在linux_kernel/driver/staging/fbtft/进行编译
***************************************************************/
